<?php
/**
 * 授权验证SDK - 主验证类
 * 
 * @author AI Assistant
 * @version 1.0.0
 */

namespace LicenseSDK;

use LicenseSDK\Http\Client;
use LicenseSDK\Storage\FileStorage;
use LicenseSDK\Hardware\MachineCode;
use LicenseSDK\Exceptions\LicenseException;

class LicenseValidator
{
    /**
     * SDK版本
     */
    const VERSION = '1.0.0';
    
    /**
     * 配置信息
     * @var array
     */
    private static $config = [];
    
    /**
     * 授权信息缓存
     * @var array|null
     */
    private static $licenseCache = null;
    
    /**
     * 上次验证时间
     * @var int
     */
    private static $lastValidateTime = 0;
    
    /**
     * 初始化SDK
     * 
     * @param array $config 配置数组
     * @throws LicenseException
     */
    public static function init(array $config)
    {
        // 必填配置项
        $required = ['api_url', 'product_code'];
        foreach ($required as $key) {
            if (empty($config[$key])) {
                throw new LicenseException("配置项 {$key} 不能为空");
            }
        }
        
        // 默认配置
        $defaults = [
            'license_key' => '',
            'license_file' => dirname(__DIR__) . '/license.dat',
            'machine_code_bind' => true,
            'domain_check' => true,
            'validate_interval' => 86400, // 24小时验证一次
            'offline_days' => 7,
            'timeout' => 10,
            'debug' => false,
        ];
        
        self::$config = array_merge($defaults, $config);
    }
    
    /**
     * 验证授权
     * 
     * @return array 验证结果
     * @throws LicenseException
     */
    public static function check()
    {
        if (empty(self::$config)) {
            throw new LicenseException('SDK未初始化，请先调用 init() 方法');
        }
        
        // 检查是否需要在线验证
        $needOnlineValidate = self::needOnlineValidate();
        
        if ($needOnlineValidate) {
            // 在线验证
            try {
                $result = self::validateOnline();
                
                if ($result['success']) {
                    // 保存验证结果到本地
                    self::saveValidateResult($result);
                    self::$licenseCache = $result;
                    self::$lastValidateTime = time();
                    
                    return $result;
                }
                
                // 在线验证失败，尝试离线验证
                if (self::canOfflineValidate()) {
                    return self::validateOffline();
                }
                
                throw new LicenseException($result['message'] ?? '授权验证失败');
                
            } catch (\Exception $e) {
                // 网络异常，尝试离线验证
                if (self::canOfflineValidate()) {
                    return self::validateOffline();
                }
                throw new LicenseException('授权验证失败: ' . $e->getMessage());
            }
        } else {
            // 使用缓存的验证结果
            return self::validateOffline();
        }
    }
    
    /**
     * 在线验证
     * 
     * @return array
     */
    private static function validateOnline()
    {
        $client = new Client(self::$config['api_url'], self::$config['timeout']);
        
        $data = [
            'license_key' => self::getLicenseKey(),
            'domain' => self::getCurrentDomain(),
            'ip' => self::getCurrentIP(),
            'machine_code' => self::$config['machine_code_bind'] ? MachineCode::generate() : null,
            'sdk_version' => self::VERSION,
            'product_version' => self::$config['product_version'] ?? null,
        ];
        
        return $client->post('/license/validate/check', $data);
    }
    
    /**
     * 离线验证
     * 
     * @return array
     */
    private static function validateOffline()
    {
        $storage = new FileStorage(self::$config['license_file']);
        $cacheData = $storage->read();
        
        if (empty($cacheData)) {
            throw new LicenseException('本地授权文件不存在或已损坏');
        }
        
        // 验证缓存数据
        if (!self::verifyCacheData($cacheData)) {
            throw new LicenseException('本地授权文件验证失败');
        }
        
        // 检查离线验证是否过期
        $offlineExpiredTime = $cacheData['validate_time'] + (self::$config['offline_days'] * 86400);
        if (time() > $offlineExpiredTime) {
            throw new LicenseException('离线验证已过期，请连接网络进行在线验证');
        }
        
        // 检查授权是否过期
        if (!empty($cacheData['end_date'])) {
            $endTime = strtotime($cacheData['end_date']);
            if (time() > $endTime) {
                throw new LicenseException('授权已过期');
            }
        }
        
        return [
            'success' => true,
            'message' => '授权验证成功（离线模式）',
            'data' => $cacheData,
            'offline' => true,
        ];
    }
    
    /**
     * 是否需要在线验证
     * 
     * @return bool
     */
    private static function needOnlineValidate()
    {
        // 强制在线验证
        if (isset(self::$config['force_online']) && self::$config['force_online']) {
            return true;
        }
        
        // 检查上次验证时间
        $storage = new FileStorage(self::$config['license_file']);
        $cacheData = $storage->read();
        
        if (empty($cacheData) || empty($cacheData['validate_time'])) {
            return true; // 没有缓存，需要在线验证
        }
        
        $interval = time() - $cacheData['validate_time'];
        return $interval >= self::$config['validate_interval'];
    }
    
    /**
     * 是否可以离线验证
     * 
     * @return bool
     */
    private static function canOfflineValidate()
    {
        $storage = new FileStorage(self::$config['license_file']);
        $cacheData = $storage->read();
        
        if (empty($cacheData)) {
            return false;
        }
        
        // 检查离线验证期限
        $offlineExpiredTime = $cacheData['validate_time'] + (self::$config['offline_days'] * 86400);
        return time() <= $offlineExpiredTime;
    }
    
    /**
     * 保存验证结果
     * 
     * @param array $result
     */
    private static function saveValidateResult(array $result)
    {
        $storage = new FileStorage(self::$config['license_file']);
        
        $data = [
            'validate_time' => time(),
            'license_key' => self::getLicenseKey(),
            'machine_code' => MachineCode::generate(),
            'license_type' => $result['data']['license_type'] ?? null,
            'license_level' => $result['data']['license_level'] ?? null,
            'end_date' => $result['data']['end_date'] ?? null,
            'remaining_days' => $result['data']['remaining_days'] ?? null,
            'features' => $result['data']['features'] ?? [],
            'max_users' => $result['data']['max_users'] ?? 0,
            'max_sites' => $result['data']['max_sites'] ?? 0,
        ];
        
        // 添加签名
        $data['signature'] = self::generateSignature($data);
        
        $storage->write($data);
    }
    
    /**
     * 验证缓存数据
     * 
     * @param array $cacheData
     * @return bool
     */
    private static function verifyCacheData(array $cacheData)
    {
        if (empty($cacheData['signature'])) {
            return false;
        }
        
        $signature = $cacheData['signature'];
        unset($cacheData['signature']);
        
        $expectedSignature = self::generateSignature($cacheData);
        
        return $signature === $expectedSignature;
    }
    
    /**
     * 生成签名
     * 
     * @param array $data
     * @return string
     */
    private static function generateSignature(array $data)
    {
        ksort($data);
        $str = json_encode($data);
        $secret = self::$config['secret_key'] ?? 'default_secret';
        
        return hash_hmac('sha256', $str, $secret);
    }
    
    /**
     * 获取授权码
     * 
     * @return string
     * @throws LicenseException
     */
    private static function getLicenseKey()
    {
        if (empty(self::$config['license_key'])) {
            throw new LicenseException('授权码未配置');
        }
        
        return self::$config['license_key'];
    }
    
    /**
     * 获取当前域名
     * 
     * @return string
     */
    private static function getCurrentDomain()
    {
        if (php_sapi_name() === 'cli') {
            return 'localhost';
        }
        
        return $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'unknown';
    }
    
    /**
     * 获取当前IP
     * 
     * @return string
     */
    private static function getCurrentIP()
    {
        $ip = '';
        
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (!empty($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        
        // 获取第一个IP（如果有多个）
        if (strpos($ip, ',') !== false) {
            $ips = explode(',', $ip);
            $ip = trim($ips[0]);
        }
        
        return $ip ?: 'unknown';
    }
    
    /**
     * 检查是否有某个功能权限
     * 
     * @param string $featureCode 功能代码
     * @return bool
     */
    public static function hasFeature($featureCode)
    {
        if (self::$licenseCache === null) {
            self::check();
        }
        
        $features = self::$licenseCache['data']['features'] ?? [];
        
        // 如果features为空，表示没有限制
        if (empty($features)) {
            return true;
        }
        
        return in_array($featureCode, $features);
    }
    
    /**
     * 获取授权信息
     * 
     * @return array|null
     */
    public static function getLicenseInfo()
    {
        if (self::$licenseCache === null) {
            try {
                self::check();
            } catch (\Exception $e) {
                return null;
            }
        }
        
        return self::$licenseCache['data'] ?? null;
    }
    
    /**
     * 获取剩余天数
     * 
     * @return int -1表示永久授权
     */
    public static function getRemainingDays()
    {
        $info = self::getLicenseInfo();
        return $info['remaining_days'] ?? 0;
    }
    
    /**
     * 清除本地缓存
     */
    public static function clearCache()
    {
        $storage = new FileStorage(self::$config['license_file']);
        $storage->delete();
        self::$licenseCache = null;
    }
    
    /**
     * 设置调试模式
     * 
     * @param bool $debug
     */
    public static function setDebug($debug = true)
    {
        self::$config['debug'] = $debug;
    }
    
    /**
     * 获取调试信息
     * 
     * @return array
     */
    public static function getDebugInfo()
    {
        return [
            'sdk_version' => self::VERSION,
            'config' => self::$config,
            'machine_code' => MachineCode::generate(),
            'domain' => self::getCurrentDomain(),
            'ip' => self::getCurrentIP(),
            'cache_exists' => file_exists(self::$config['license_file'] ?? ''),
        ];
    }
}

